﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
    public class CallerMemberNameAttribute : Attribute { }

    [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
    public class CallerFilePathAttribute : Attribute { }

    [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
    public class CallerLineNumberAttribute : Attribute { }
}
namespace TaiwuZD
{
    public class BindableBase : INotifyPropertyChanged
    {

        /// <summary>
        /// 
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="storage"></param>
        /// <param name="value"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        protected bool SetProperty<T>(ref T storage, T value, [System.Runtime.CompilerServices.CallerMemberName] String propertyName = null)
        {
            if (string.IsNullOrEmpty(propertyName)) return false;
            if (object.Equals(storage, value)) return false;
            try
            {
                storage = value;
                //ThreadPool.QueueUserWorkItem(new WaitCallback(NotifyPropertyChanged), propertyName);

                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="propertyName"></param>
        protected void NotifyPropertyChanged(object propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs((string)propertyName));
            }
        }
    }

    public class TwDictionary : Dictionary<string, string>
    {
        public new string this[string key]
        {
            get
            {
                if (Keys.Contains(key))
                    return base[key];
                else
                    return "0";
            }
            set
            {
                if (Keys.Contains(key))
                    base[key] = value;
                else if (value != "0")
                    Add(key, value);
            }
        }

        public string this[int key]
        {
            get
            {
                return this[key.ToString()];
            }
            set
            {
                this[key.ToString()] = value;
            }
        }

        public TwDictionary() { }

        public TwDictionary(Dictionary<string, string> dic)
        {
            foreach (var item in dic)
            {
                if (item.Value.Trim() != "0")
                Add(item.Key, item.Value);
            }
        }
        public TwDictionary(Dictionary<int, string> dic)
        {
            foreach (var item in dic)
            {
                if (item.Value.Trim() != "0")
                    Add(item.Key.ToString(), item.Value);
            }
        }
    }

    public abstract class TwObject:BindableBase,ICloneable
    {
        [JsonIgnore]
        public virtual int Id
        {
            get { return int.Parse(DataShop[999]); }
            protected set { DataShop[999] = value.ToString(); }
        }

        [JsonIgnore]
        public virtual string Name
        {
            get { return DataShop[0]; }
            protected set { DataShop[0] = value; }
        }

        [JsonIgnore]
        public virtual string Description
        {
            get { return DataShop[99]; }
            protected set { DataShop[99] = value; }
        }

        [JsonProperty]
        protected TwDictionary DataShop { get; set; } = new TwDictionary();


        public virtual string this[string key]
        {
            get
            {
                if (DataShop.ContainsKey(key))
                    return DataShop[key];
                else
                    return "0";
            }
        }

        public virtual string this[int key]
        {
            get
            {
                return this[key.ToString()];
            }
        }

        public T ValueAt<T>(string key) where T : struct
        {
            var tmp = this[key];

            if (typeof(T) == typeof(int))
            {
                int d = 0;
                int.TryParse(tmp, out d);
                return (T)Convert.ChangeType(d, typeof(T));
            }
            else if (typeof(T).IsEnum)
            {
                int d = 0;
                int.TryParse(tmp, out d);
                return (T)Enum.ToObject(typeof(T), d);// (int)Convert.ChangeType(d, typeof(int)));
            }
            else
                throw new NotSupportedException();
        }
        public T ValueAt<T>(int key) where T : struct
        {
            return ValueAt<T>(key.ToString());
        }

        protected void SetData(JProperty jp)
        {
            foreach (JProperty item in jp.Value)
            {
                DataShop[item.Name] = item.Value.ToString();
            }
        }

        public void SetData(int key,string value)
        {
            var kk = key.ToString();
            if (DataShop.ContainsKey(kk))
                DataShop[kk] = value;
            else
                DataShop.Add(kk, value);
        }
        public void SetData(int key, int value)
        {
            var kk = key.ToString();
            if (DataShop.ContainsKey(kk))
                DataShop[kk] = value.ToString();
            else
                DataShop.Add(kk, value.ToString());
        }

        public void SetData(string key, string value)
        {  
            if (DataShop.ContainsKey(key))
                DataShop[key] = value;
            else
                DataShop.Add(key, value);
        }
        public void SetData(Dictionary<int, string> savedata)
        {
            foreach (var item in savedata)
            {
                DataShop[item.Key] = item.Value;
            }
        }

       

        public T Copy<T>() where T : TwObject
        {
            T x = typeof(T).GetConstructor(Type.EmptyTypes).Invoke(null) as T;
            x.Id = Id;
            x.Name = Name;
            x.Description = Description;
            x.DataShop = new TwDictionary(this.DataShop);
            return x;
        }

        public abstract object Clone();

      

        
    }

    

}
